package com.sea.base.anim

import android.animation.Animator
import android.view.View
import androidx.core.view.updateLayoutParams
import com.sea.base.R
import com.sea.base.ext.view.ViewGroupLayoutParams
import com.sea.base.ext.view.WRAP_CONTENT
import com.sea.base.ext.view.getTypeTag
import kotlin.math.abs

object AnimUtil {
    /**
     * 高度由当前变成wrap的动画
     * 宽必须固定，高必须wrap（如果不是此条件，自己写简单动画就行了）
     * 注意：对于RecyclerView的FlexboxLayoutManager可能会崩溃
     */
    @JvmStatic
    fun animHeightWrap(view: View, startHeight: Int = view.measuredHeight, viewWidth: Int = view.measuredWidth, duration: Long = 300L) {
        view.measure(
            View.MeasureSpec.makeMeasureSpec(viewWidth, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(9999, View.MeasureSpec.UNSPECIFIED),
        )

        val newHeight = view.measuredHeight
        if (abs(newHeight - startHeight) < 2) {
            return
        }

        val anim = MyValueAnimator.ofInt(startHeight, newHeight)
        anim.addListener {
            view.updateLayoutParams<ViewGroupLayoutParams> {
                height = WRAP_CONTENT
            }
        }
        anim.addUpdateListener { h ->
            view.updateLayoutParams<ViewGroupLayoutParams> {
                height = h
            }
        }
        anim.duration = duration
        anim.start(view)
    }

    fun animHeight(view: View, toHeight: Int = 0, duration: Long = 300L) {
        animHeight(view, toHeight, duration) {}
    }

    /**
     * 从当前变到指定高度
     * @param toHeight 指定高度，默认0
     */
    @JvmStatic
    inline fun animHeight(view: View, toHeight: Int = 0, duration: Long = 300L, crossinline onEndCallback: () -> Unit) {
        val oldHeight = view.height
        if (oldHeight == toHeight) {
            onEndCallback.invoke()
            return
        }
        val anim = MyValueAnimator.ofInt(oldHeight, toHeight)
        anim.addListener {
            view.updateLayoutParams<ViewGroupLayoutParams> {
                height = toHeight
                onEndCallback.invoke()
            }
        }
        anim.addUpdateListener { h ->
            view.updateLayoutParams<ViewGroupLayoutParams> {
                height = h
            }
        }
        anim.duration = duration
        anim.start(view)
    }

    fun cancelAnim(view: View) {
        getAnimTag(view)?.cancel()
    }

    fun pauseAnim(view: View) {
        (getAnimTag(view))?.pause()
    }

    fun getAnimTag(view: View) = view.getTypeTag<Animator>(R.id.tag_anim)
}